package com.bruce.rpc;

import com.bruce.rpc.connection.ZkConnection;
import com.bruce.rpc.registry.RpcRegistry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;

import java.io.IOException;
import java.io.InputStream;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.util.List;
import java.util.Properties;

/**
 * 框架入口
 * @author Bruce
 */
public class RpcFactory {
    private static final Properties CONFIG = new Properties();
    private static final ZkConnection CONNECTION;
    private static final RpcRegistry REGISTRY;
    private static final Properties service = new Properties();

    static {
        InputStream input = RpcFactory.class.getClassLoader().getResourceAsStream("bruce-rpc.properties");
        try {
            CONFIG.load(input);
            //获取服务端IP
            String serverIp = CONFIG.getProperty("registry.ip") == null ? "localhost" : CONFIG.getProperty("registry.ip");
            int serverPort = CONFIG.getProperty("registry.port") == null ? 9090 : Integer.parseInt(CONFIG.getProperty("registry.port"));
            //zk服务器配置地址
            String zkServer = CONFIG.getProperty("zk.server") == null ? "localhost:2181" : CONFIG.getProperty("zk.server");
            //zk客户端会话超时配置
            int zkSessionTimeout = CONFIG.getProperty("zk.sessionTimeout") == null ? 10000 : Integer.parseInt(CONFIG.getProperty("zk.sessionTimeout"));
            CONNECTION = new ZkConnection(zkServer, zkSessionTimeout);
            REGISTRY = new RpcRegistry();
            REGISTRY.setIp(serverIp);
            REGISTRY.setPort(serverPort);
            REGISTRY.setConnection(CONNECTION);
            //创建一个RMI注册器
            LocateRegistry.createRegistry(serverPort);

            //初始化zk中的父节点
            List<String> children = CONNECTION.getConnection().getChildren("/", false);
            if (!children.contains("bruce")){
                CONNECTION.getConnection().create("/bruce", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            List<String> bruceChildren = CONNECTION.getConnection().getChildren("/bruce", false);
            if (!bruceChildren.contains("rpc")){
                CONNECTION.getConnection().create("/bruce/rpc", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }


            InputStream serviceInput = RpcFactory.class.getClassLoader().getResourceAsStream("bruce-rpc-service.properties");
            if(serviceInput != null){
                service.load(serviceInput);
                for(Object key : service.keySet()){
                    Object value = service.get(key);
                    //key 接口的全命名   value 实现类的全命名
                    Class<Remote> serviceInterface = (Class<Remote>) Class.forName(key.toString());
                    Remote serviceObject = (Remote) Class.forName(value.toString()).newInstance();
                    REGISTRY.registerService(serviceInterface, serviceObject);
                }
            }

        } catch (IOException | KeeperException | InterruptedException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new ExceptionInInitializerError();
        }
    }

    //快速注册服务和创建客户端代理对象
    public static void registerService(Class<? extends Remote> serviceInterface, Remote serviceObject) throws IOException, InterruptedException, KeeperException {
        REGISTRY.registerService(serviceInterface, serviceObject);
    }

    public static <T extends Remote> T getServiceProxy(Class<T> serviceInterface) throws NotBoundException, IOException, InterruptedException, KeeperException {
        return REGISTRY.getServiceProxy(serviceInterface);
    }

}
